using UnityEngine;
using System.Collections;

public class MarbleControl : MonoBehaviour
{

    public float movementSpeed = 6.0f;
	
	public Material woodMat;
	public Material steelMat;
	public Material paperMat;
	public AudioClip rollStoneStone;
	public AudioClip rollWoodStone;
	public AudioClip rollStoneMetal;
	public AudioClip rollWoodMetal;
	public AudioClip rollStoneWood;
	public AudioClip rollWoodWood;
	public AudioClip rollPaper;

	public AudioClip hitStoneMetal;
	public AudioClip hitWoodMetal;
	public AudioClip hitStoneWood;
	public AudioClip hitWoodWood;
	public AudioClip hitStoneStone;
	public AudioClip hitWoodStone;
	public AudioClip hitPaper;
	public AudioClip hitGameOver;
    public AudioClip hitChanger;
	
	
	
	private float unpauseTime = 0.0f;
	private float startParticlesTime = 0.0f;
	private Vector3 changerPos = new Vector3(0,0,0);
	private Vector3 lastVelocity = new Vector3(0,0,0);
	private int activeHitSource = 0;

	public enum Type
	{
		Steel,
		Wood,
		Paper		
	};
	
	public enum ColMat
	{
		None,
		Metal,
		Wood,
		Stone,
		GameOver,
        Changer
	};

    private enum State
    {
        Moving,
        Falling,
        Changing
    };

    private State state = State.Moving;
	
	private int colMetal = 0;
	private int colStone = 0;
	private int colWood = 0;
	private float colMetalSmooth = 0.0f;
	private float colStoneSmooth = 0.0f;
	private float colWoodSmooth = 0.0f;
	private float looseLifeTime = 0.0f;
	
	private AudioSource rollSoundStone;
	private AudioSource rollSoundMetal;
	private AudioSource rollSoundWood;
	
	private AudioSource hitSound1;
	private AudioSource hitSound2;

	public Type type = Type.Paper;
	public Type targetType = Type.Paper;

    private Quaternion groundRot;
    private Vector3 prevStrafe;

	void Awake()
	{
		colMetal = 0;
		colStone = 0;
		colWood = 0;
		colMetalSmooth = 0.0f;
		colStoneSmooth = 0.0f;
		colWoodSmooth = 0.0f;

        groundRot = Quaternion.identity;

        state = State.Moving;

        prevStrafe = -Vector3.right;
		
		rollSoundStone = gameObject.AddComponent<AudioSource>();
		rollSoundStone.loop = true;
		rollSoundStone.rolloffMode = AudioRolloffMode.Linear;
		rollSoundMetal = gameObject.AddComponent<AudioSource>();
		rollSoundMetal.loop = true;
		rollSoundMetal.rolloffMode = AudioRolloffMode.Linear;
		rollSoundWood = gameObject.AddComponent<AudioSource>();
		rollSoundWood.loop = true;
		rollSoundWood.rolloffMode = AudioRolloffMode.Linear;
		
		hitSound1 = gameObject.AddComponent<AudioSource>();
		hitSound1.rolloffMode = AudioRolloffMode.Linear;
		hitSound2 = gameObject.AddComponent<AudioSource>();
		hitSound2.rolloffMode = AudioRolloffMode.Linear;
	}

    void FixedUpdate()
    {
        lastVelocity = rigidbody.velocity;
    }

	void Update ()
    {
        Vector3 fixedUp = rigidbody.transform.position;
        fixedUp.Normalize();
        //MarbleCamera.Instance.up = fixedUp;
		updateRollSound();
		
		Vector3 gravity = new Vector3(0.0f,-9.8f,0.0f);//-rigidbody.transform.position;
		//gravity.Normalize();
		//gravity = gravity * 9.8f;

		rigidbody.AddForce(gravity, ForceMode.Acceleration);
		
	
        switch (state)
        {
        case State.Moving:
            processMoving();
            break;
        case State.Falling:
            processFalling();
            break;
        case State.Changing:
            processChanging();
            break;
        }
	}

    void processMoving()
    {
        RaycastHit hit;
        if (Physics.Raycast(transform.position, -transform.position, out hit, 2.0f, ~(1<<8)))
        {
            Debug.Log(hit.collider.gameObject.name);
            groundRot = hit.collider.transform.rotation;
        }

        float angle = MarbleCamera.Instance.angle * Mathf.Rad2Deg;
        Quaternion rot = groundRot * 
			Quaternion.Euler(0, angle, 0) ;

        float movementSpeed = getMovementSpeed();

        float axisX = Input.GetAxis("Horizontal");
        float axisY = Input.GetAxis("Vertical");
        Vector3 fwd = rot * -Vector3.forward;
        Vector3 strafe = rot * -Vector3.right;

        Vector3[] dirs = new Vector3[4];

        dirs[0] = fwd;
        dirs[1] = strafe;
        dirs[2] = -fwd;
        dirs[3] = -strafe;


        for (int i = 0; i < 4; ++i)
        {
            if (Vector3.Dot(dirs[i], prevStrafe) > 0.7f)
            {
                strafe = dirs[i];
                fwd = dirs[(i + 3)%4];
                break;

            }

        }

        prevStrafe = strafe;


        MarbleCamera.Instance.strafe = Vector3.Lerp(MarbleCamera.Instance.strafe, strafe, Time.deltaTime*5.0f) ;
   

        Vector3 movement = (axisX * strafe + axisY * fwd) * movementSpeed * Time.deltaTime;
        //movement.y -= movement.magnitude;  //push ball down when rolling

        rigidbody.AddForce(movement, ForceMode.Force);

        bool inWater = (rigidbody.drag == 6.0f);

        if (inWater)
        {
            const float fakeRotationSpeed = 3.0f;
            // process bouyancy
            rigidbody.AddTorque((-fwd * axisX + strafe * axisY) * fakeRotationSpeed);
        }
    }

    void startFalling()
    {
		MarbleCamera.Instance.touchGameOverPos = rigidbody.transform.position;
		MarbleCamera.Instance.freeFly = true;
        looseLifeTime = Time.time + 1.5f;
        state = State.Falling;
    }

    void processFalling()
    {
        if (looseLifeTime < Time.time)
        {
            MarbleGameManager.Instance.SetGameOver();
            state = State.Moving;
        }
    }

	void OnCollisionEnter (Collision info )
	{
		Vector3 deltaVelocity = (rigidbody.velocity - lastVelocity);

		float hitVolume = deltaVelocity.magnitude / 10.0f;

		if (lastVelocity.magnitude < rigidbody.velocity.magnitude)
		{
            hitVolume = 0.0f;
		}

		if (info.gameObject.tag == "Metal")
		{
			addCol(ColMat.Metal);
            if (hitVolume > 0.03)
			{
				if (info.relativeVelocity.magnitude > 1)
				{
                    playHitSound(hitVolume, ColMat.Metal);
				}
			}
		}
		else if (info.gameObject.tag == "Stone")
		{
			addCol(ColMat.Stone);

            if (hitVolume > 0.03)
			{
				if (info.relativeVelocity.magnitude > 1)
				{
                    playHitSound(hitVolume, ColMat.Stone);
				}
			}
		}
		else if (info.gameObject.tag == "Wood")
		{
			addCol(ColMat.Wood);
            if (hitVolume > 0.03)
			{
				if (info.relativeVelocity.magnitude > 1)
				{
                    playHitSound(hitVolume, ColMat.Wood);
				}
			}
		}
        MarbleGameManager.Instance.onAddCollision();
	}
	
	void OnCollisionStay(Collision info)
	{
	}
	
	void OnCollisionExit(Collision info )
	{
        MarbleGameManager.Instance.onRemoveCollision();
		
		if (info.gameObject.tag == "Metal")
		{
			removeCol(ColMat.Metal);
		}
		else if (info.gameObject.tag == "Stone")
		{
			removeCol(ColMat.Stone);
		}
		else if (info.gameObject.tag == "Wood")
		{
			removeCol(ColMat.Wood);
		}
	}

    void OnTriggerEnter  (Collider other  )
    {
		if (other.tag == "GameOver")
		{
			playHitSound(0.5f, ColMat.GameOver);
            startFalling();
		}
		if (other.tag == "Water")
		{
			rigidbody.drag = 6.0f;
			rigidbody.angularDrag = 5.0f;
		}
        else if (other.tag == "Pickup")
        {
            MarbleGameManager.Instance.FoundGem();
            Destroy(other.gameObject);
			rigidbody.AddForce(Vector3.up*4.0f, ForceMode.Impulse);
        }
		else if (other.tag == "WoodChanger")
		{
            changeBall(Type.Wood, other.gameObject.transform.position);
		}
		else if (other.tag == "PaperChanger")
		{
			Debug.Log("dsfdsf");
            changeBall(Type.Paper, other.gameObject.transform.position);
		}
		else if (other.tag == "StoneChanger")
		{
            changeBall(Type.Steel, other.gameObject.transform.position);
		}
        else
        {
            //Other collider.. See other.tag and other.name
        }        
    }

    void OnTriggerStay(Collider other)
    {
        if (other.tag == "Flyer")
        {
            rigidbody.AddForce(Vector3.up * 19.6f * 0.1f);
        }
        if (other.tag == "Water")
        {
            float r = 0.75f;
            float h = r + 47.5f - rigidbody.position.y;
            float vol = 3.14f * h * h * (3.0f * r - h) / 3.0f;
            float fullVol = 3.14f * r * r * r * 4.0f / 3.0f;

            rigidbody.AddForce(Vector3.up * 7.0f * vol / fullVol);
        }
    }

    void OnTriggerExit(Collider other)
    {
        if (other.tag == "Water")
        {
            rigidbody.drag = 0.5f;
            rigidbody.angularDrag = 0.05f;
        }

    }

    float getMovementSpeed()
    {
        float movementSpeed = 0.0f;
        if (type == Type.Paper)
        {
            movementSpeed = 60.3f;
        }
        else if (type == Type.Wood)
        {
            movementSpeed = 300.0f;
        }
        else if (type == Type.Steel)
        {
            movementSpeed = 3000.0f;
        }
        return movementSpeed;
    }

    void processChanging()
    {
        Vector3 dir = changerPos - rigidbody.transform.position;
        float dist = dir.magnitude;
        dir.Normalize();
        Vector3 diff = dir * dist * 5.2f - rigidbody.velocity;

        rigidbody.AddForce(diff, ForceMode.VelocityChange);

        if (Time.time > startParticlesTime)
        {
            particleEmitter.emit = true;
        }

        if (Time.time > unpauseTime)
        {
            if (targetType == Type.Paper)
            {
                renderer.material = paperMat;
                rigidbody.mass = 0.09f;  //поменяла массу была 0.13

            }
            else if (targetType == Type.Wood)
            {
                renderer.material = woodMat;
                rigidbody.mass = 0.7f;
            }
            else if (targetType == Type.Steel)
            {
                renderer.material = steelMat;
                rigidbody.mass = 7.0f;
            }
            type = targetType;
            state = State.Moving;
            particleEmitter.emit = false;
        }
    }

    void playHitSound(float volume, ColMat mat)
    {
        AudioSource src = hitSound1;
        if (activeHitSource == 1)
        {
            src = hitSound2;
            activeHitSource = 0;
        }
        else
        {
            activeHitSource = 1;
        }
        if (mat == ColMat.Metal)
        {
            if (type == Type.Steel)
            {
                src.clip = hitStoneMetal;
            }
            else if (type == Type.Wood)
            {
                src.clip = hitWoodMetal;
            }
            else if (type == Type.Paper)
            {
                src.clip = hitPaper;
            }
        }
        else if (mat == ColMat.Wood)
        {
            if (type == Type.Steel)
            {
                src.clip = hitStoneWood;
            }
            else if (type == Type.Wood)
            {
                src.clip = hitWoodWood;
            }
            else if (type == Type.Paper)
            {
                src.clip = hitPaper;
            }
        }
        else if (mat == ColMat.Stone)
        {
            if (type == Type.Steel)
            {
                src.clip = hitStoneStone;
            }
            else if (type == Type.Wood)
            {
                src.clip = hitWoodStone;
            }
            else if (type == Type.Paper)
            {
                src.clip = hitPaper;
            }
        }
        else if (mat == ColMat.GameOver)
        {
            src.clip = hitGameOver;
        }
        else if (mat == ColMat.Changer)
        {
            src.clip = hitChanger;
        }

        src.Play();
        src.loop = false;
        src.volume = volume;
    }

    AudioClip getRollSound(ColMat col)
    {
        if (type == Type.Steel)
        {
            if (col == ColMat.Metal)
            {
                return rollStoneMetal;
            }
            else if (col == ColMat.Wood)
            {
                return rollStoneWood;
            }
            return rollStoneStone;
        }
        else if (type == Type.Wood)
        {
            if (col == ColMat.Metal)
            {
                return rollWoodMetal;
            }
            else if (col == ColMat.Wood)
            {
                return rollWoodWood;
            }
            return rollWoodStone;
        }
        else if (type == Type.Paper)
        {
            return rollPaper;
        }
        return rollPaper;
    }

    void updateRollSound()
    {
        if (colMetal > 0)
        {
            colMetalSmooth = colMetal;
        }
        else
        {
            colMetalSmooth -= Time.deltaTime * 8.0f;
        }

        if (colStone > 0)
        {
            colStoneSmooth = colStone;
        }
        else
        {
            colStoneSmooth -= Time.deltaTime * 8.0f;
        }

        if (colWood > 0)
        {
            colWoodSmooth = colWood;
        }
        else
        {
            colWoodSmooth -= Time.deltaTime * 8.0f;
        }

        float volume = rigidbody.velocity.magnitude / 10.0f;
        rollSoundStone.volume = volume;
        rollSoundMetal.volume = volume;
        rollSoundWood.volume = volume;

        if (colMetalSmooth > 0.5f)
        {
            AudioClip newClip = getRollSound(ColMat.Metal);
            if (newClip != rollSoundMetal.clip || !rollSoundMetal.isPlaying)
            {
                rollSoundMetal.clip = newClip;
                rollSoundMetal.Play();
            }
        }
        else
        {
            rollSoundMetal.Stop();
        }
        if (colStoneSmooth > 0.5f)
        {
            AudioClip newClip = getRollSound(ColMat.Stone);
            if (newClip != rollSoundStone.clip || !rollSoundStone.isPlaying)
            {
                rollSoundStone.clip = newClip;
                rollSoundStone.Play();
            }
        }
        else
        {
            rollSoundStone.Stop();
        }
        if (colWoodSmooth > 0.5f)
        {
            AudioClip newClip = getRollSound(ColMat.Wood);
            if (newClip != rollSoundWood.clip || !rollSoundWood.isPlaying)
            {
                rollSoundWood.clip = newClip;
                rollSoundWood.Play();
            }
        }
        else
        {
            rollSoundWood.Stop();
        }
    }

    void addCol(ColMat col)
    {
        if (col == ColMat.Metal)
        {
            colMetal++;
        }
        else if (col == ColMat.Stone)
        {
            colStone++;
        }
        else if (col == ColMat.Wood)
        {
            colWood++;
        }
    }

    void removeCol(ColMat col)
    {
        if (col == ColMat.Metal)
        {
            colMetal--;
        }
        else if (col == ColMat.Stone)
        {
            colStone--;
        }
        else if (col == ColMat.Wood)
        {
            colWood--;
        }
    }

    void changeBall(Type new_type, Vector3 pos)
    {
        if (type != new_type)
        {
			Debug.Log("do change");
            playHitSound(0.5f, ColMat.Changer);
            changerPos = pos;
            targetType = new_type;

            state = State.Changing;
            unpauseTime = Time.time + 1.5f;
            startParticlesTime = Time.time + 0.5f;
        }
    }

}
